package com.moss.cloud.base.biz.listener;

import com.moss.cloud.base.biz.event.*;
import com.moss.cloud.base.biz.model.AccountLockHistoryRecord;
import com.moss.cloud.base.biz.service.IAccountLockHistoryRecordService;
import com.moss.cloud.base.biz.service.ISysUserService;
import com.moss.cloud.common.core.constant.MsgTopic;
import com.moss.cloud.common.core.enums.MsgActionEnum;
import com.moss.cloud.common.core.enums.MsgTypeEnum;
import com.moss.cloud.common.core.model.dto.MessageDTO;
import com.moss.cloud.common.core.model.dto.UserEventDTO;
import com.moss.cloud.common.security.component.MessageEventSender;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;

/**
 * 用户事件处理中心--此类消息必须是事务处理完成之后再调用
 *
 * @author 瑾年
 * @date 2023年3月25日
 */
@Slf4j
@Component
public class UserListener {

    private final MessageEventSender messageEventSender;
    private final ISysUserService sysUserService;
    private final IAccountLockHistoryRecordService accountLockHistoryRecordService;

    public UserListener(MessageEventSender messageEventSender, ISysUserService sysUserService,
                        IAccountLockHistoryRecordService accountLockHistoryRecordService) {
        this.messageEventSender = messageEventSender;
        this.sysUserService = sysUserService;
        this.accountLockHistoryRecordService = accountLockHistoryRecordService;
    }

    /**
     * 监听用户创建事件
     * 发布一个用户创建的MQ消息-供业务系统监听用户创建更新本地用户信息
     * 这种方式是为了解决避免多次feign调用消耗网络资源，同时业务系统中也有自己的用户体系，自定的用户信息等
     * 也能解决业务系统中联查用户信息的问题
     * 虽不能保证实时数据一致性，但是可以保证最终一致性
     *
     * @param event
     */
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void handleUserCreateEvent(UserCreateEvent event) {
        log.info("监听用户创建事件->用户名:{}", event.getSysUser().getUsername());
        UserEventDTO dto = new UserEventDTO();
        BeanUtils.copyProperties(event.getSysUser(), dto);
        // 发布一个用户创建的MQ消息-供业务系统监听用户创建更新本地用户信息
        messageEventSender.sendMessage(MsgTopic.BASE_USER_ADD_MESSAGE, new MessageDTO(MsgTypeEnum.ONE.name(), MsgActionEnum.ADD.name(), dto));
    }

    /**
     * 监听用户删除事件
     *
     * @param event
     */
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void handleUserRemoveEvent(UserRemoveEvent event) {
        log.info("监听用户删除事件->用户名:{}", event.getSysUser().getUsername());
        UserEventDTO dto = new UserEventDTO();
        BeanUtils.copyProperties(event.getSysUser(), dto);
        messageEventSender.sendMessage(MsgTopic.BASE_USER_DEL_MESSAGE, new MessageDTO(MsgTypeEnum.ONE.name(), MsgActionEnum.DELETE.name(), dto));
    }

    /**
     * 监听用户修改事件
     *
     * @param event
     */
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void handleUserUpdateEvent(UserUpdateEvent event) {
        log.info("监听用户更新事件->用户名:{}", event.getSysUser().getUsername());
        UserEventDTO dto = new UserEventDTO();
        BeanUtils.copyProperties(event.getSysUser(), dto);
        messageEventSender.sendMessage(MsgTopic.BASE_USER_UPD_MESSAGE, new MessageDTO(MsgTypeEnum.ONE.name(), MsgActionEnum.UPDATE.name(), dto));
    }

    /**
     * 监听用户账号解锁事件
     *
     * @param event
     */
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void handleUserlockEvent(UserLockEvent event) {
        log.info("监听用户账号解锁/锁定事件->用户ID:{}", event.getUserEventDTO().getUserId());
        // 锁定时增加锁定历史记录
        AccountLockHistoryRecord record = new AccountLockHistoryRecord();
        BeanUtils.copyProperties(event.getUserEventDTO(),record);
        accountLockHistoryRecordService.addHistoryRecord(record);
        messageEventSender.sendMessage(MsgTopic.BASE_USER_LOCK_MESSAGE, new MessageDTO(MsgTypeEnum.ONE.name(), MsgActionEnum.UPDATE.name(), event.getUserEventDTO()));
    }

    /**
     * 监听用户租户更新事件
     *
     * @param event
     */
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void handleUpdateUserTenantEvent(UpdateUserTenantEvent event) {
        log.info("监听用户租户更新事件->用户ID:{}", event.getUpdateUserTenantFrom().getUserId());
        sysUserService.updateUserTenant(event.getUpdateUserTenantFrom());
    }

    /**
     * 监听租户员工离职事件
     *
     * @param event
     */
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void handleUpdateUserTenantEvent(UserDepartEvent event) {
        log.info("监听用租户员工离职事件->用户ID:{}", event.getUserId());
        // 这里可以处理离职之后的其他事情，也可以使用MQ通知其他业务服务处理员工离职后续的操作
    }

}
